/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.signature_factory;

import picounit.features.base.ProxyFactory;
import picounit.features.parameter_name.MethodParameterRegistry;
import picounit.features.registry.Resolver;
import picounit.mocker.MockFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Signature {
	private final String[] parameterNames;
	private final Parameter[] parameters;
	private final Class[] parameterTypes;
	private final String name;
	private final Class declaringClass;

	public Signature(Constructor constructor, MethodParameterRegistry methodParameterRegistry,
		Resolver resolver, MockFactory mockFactory, ProxyFactory proxyFactory,
		InvocationHandler collaboratorsInvocationHandler) {

		this("<init>", methodParameterRegistry.get(constructor), constructor.getParameterTypes(),
			constructor.getDeclaringClass(), resolver, mockFactory, proxyFactory, collaboratorsInvocationHandler);
	}

	public Signature(Method method, MethodParameterRegistry methodParameterRegistry,
		Resolver resolver, MockFactory mockFactory, ProxyFactory proxyFactory,
		InvocationHandler collaboratorsInvocationHandler) {

		this(method.getName(), methodParameterRegistry.get(method), method.getParameterTypes(),
			method.getDeclaringClass(), resolver, mockFactory, proxyFactory, collaboratorsInvocationHandler);
	}

	public Signature(String name, String[] parameterNames, Class[] parameterTypes,
		Class declaringClass, Resolver resolver, MockFactory mockFactory, ProxyFactory proxyFactory,
		InvocationHandler collaboratorsInvocationHandler) {

		this.name = name;
		this.parameterNames = parameterNames;
		this.parameterTypes = parameterTypes;
		this.declaringClass = declaringClass;

		this.parameters = Parameter.create(this, parameterNames, parameterTypes, declaringClass,
			mockFactory, resolver, proxyFactory, collaboratorsInvocationHandler);
	}

	public String name() {
		return name;
	}

	public Parameter[] parameters() {
		return parameters;
	}

	public Class[] parameterTypes() {
		return parameterTypes;
	}

	public String[] parameterNames() {
		return parameterNames;
	}

	public Class declaringClass() {
		return declaringClass;
	}

	public Object[] parameterValues() {
		return new CollectionUtil().convert(parameters, Parameter.VALUE_CONVERTER);
	}

	public int numMatching() {
		int numMatching1 = 1;

		for (Parameter parameter : parameters()) { 
			numMatching1 *= parameter.numMatching();
		}

		return numMatching1;
	}
}
